/**
Copyright 2011 Michael Shick

This file is part of Joggle.

Joggle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Joggle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Joggle.  If not, see <http://www.gnu.org/licenses/>.
*/
package edu.gwu.cs.joggle;

import java.net.InetAddress;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;

/**
 * Manager for connections to a Joggle server.
 * @author Michael Shick <mfshick@gwmail.gwu.edu>
 * @version 0.1
 * @since alpha
 */
public class Session
{
    /** Server address used when none is specified by user */
    public static final String DEFAULT_HOST = "localhost";
    /** Server port used when none is specified by user */
    public static final int DEFAULT_PORT = 5402;
    /** Server key used when none is specified by user */
    public static final PublicKey DEFAULT_KEY = null;
    /** Separator for human-readable host / port pair strings*/
    public static final String LOCATION_SEPARATOR = ":";
    /** Indicators of human-readable host / port part string order */
    public static final int ADDRESS_PART = 0, PORT_PART = 1;

    /** Human-readable exception messages */
    public static final String
        NULL_ARGUMENT_MESSAGE = "non-optional argument passed as null",
        MALFORMED_LOCATION_MESSAGE = "malformed location";

    private Connection connection;
    private int status;

    /**
     * Creates empty, inactive session.
     */
    public Session()
    {
        connection = null;
        status = Connection.INACTIVE;
    }

    /**
     * Attempts to open session with default server.
     * @param username user to authenticate as
     * @param password password for requested user
     * @return int status of session after connection attempt as described by
     * Connection status variables
     */
    public int open(String username, String password)
        throws java.net.UnknownHostException
    {
        InetAddress address = InetAddress.getByName(DEFAULT_HOST);
        return open(username, password, address, DEFAULT_PORT, DEFAULT_KEY);
    }

    /**
     * Attempts to open session with server specified by human-readable string.
     * @param username user to authenticate as
     * @param password password for requested user
     * @param serverLocation non-null; of the form "host:port"
     * @param serverKey key used to verify integrity and authorship of messages,
     * or null for an unsafe connection
     * @return int status of session after connection attempt as described by
     * Connection status variables
     */
    public int open(String username, String password, String serverLocation,
            PublicKey serverKey)
        throws java.net.UnknownHostException
    {
        if(serverLocation == null)
        {
            throw new java.lang.IllegalArgumentException(NULL_ARGUMENT_MESSAGE);
        }
        String[] locationParts = serverLocation.split(LOCATION_SEPARATOR);
        if(locationParts.length != 2)
        {
            throw new java.lang.IllegalArgumentException(
                    MALFORMED_LOCATION_MESSAGE + " '" + serverLocation + "'");
        }
        InetAddress address = InetAddress.getByName(
                locationParts[ADDRESS_PART]);
        int port = Integer.parseInt(locationParts[PORT_PART]);
        return open(username, password, address, port, serverKey);
    }
    
    /**
     * Attempts to open session with server specified by machine-readable
     * address / port pair.
     * @param username user to authenticate as
     * @param password password for requested user
     * @param serverLocation non-null; of the form "host:port"
     * @param serverKey key used to verify integrity and authorship of messages,
     * or null for an unsafe connection
     * @return int status of session after connection attempt as described by
     * Connection status variables
     */
    public int open(String username, String password, InetAddress serverAddress,
            int serverPort, PublicKey serverKey)
    {
        if(username == null || password == null || serverAddress == null)
        {
            throw new java.lang.IllegalArgumentException(NULL_ARGUMENT_MESSAGE);
        }
        connection = new Connection(serverAddress, serverPort);
        status = connection.connect();
        return status;
    }

    /**
     * Fetch user profile from server
     * @param Profile username user id of user whose profile is requested
     */
    public Profile getProfile(String username)
    {
        if(username == null)
        {
            throw new java.lang.IllegalArgumentException(NULL_ARGUMENT_MESSAGE);
        }
        return null;
    }

    /**
     * Closes connections to server and cleans up
     * @return int status of session after close as described by Connection status
     * variables
     */
    public int close()
    {
        status = Connection.CLOSED;
        return status;
    }

    /**
     * Queries session status
     * @return int current status as described by Connection status variables
     */
    public int getStatus()
    {
        return status;
    }
}
